package com.xsj.service.impl;

import com.xsj.mapper.CardMapper;
import com.xsj.pojo.Card;
import com.xsj.service.CardService;
import com.xsj.vo.CardVO;
import com.xsj.vo.Cart;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;

/**
 * @BelongsProject: wisdom-restaurant-manage
 * @BelongsPackage: com.xsj.service.impl
 * @Author: tutu
 * @CreateTime: 2025-06-22 21:39
 * @Description: TODO
 * @Version: 1.0
 */

@Service
@Transactional
@Slf4j
public class CardServiceImpl implements CardService {

    @Autowired
    private CardMapper cardMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

//    @Autowired
//    private StreamBridge streamBridge;

    private static final String CLAIM_COUPON_LUA_SCRIPT =
            "if redis.call('SISMEMBER', KEYS[2], ARGV[1]) == 1 then return 1 end; " +
            "local stock = tonumber(redis.call('GET', KEYS[1])); " +
            "if not stock or stock <= 0 then return 2 end; " +
            "redis.call('DECR', KEYS[1]); " +
            "redis.call('SADD', KEYS[2], ARGV[1]); " +
            "return 0;";

    @Override
    public Card addCard(CardVO cardRequest) throws Exception {

        // 1. 定义Redis Keys 和执行Lua脚本 (修正键名)
        String stockKey = "coupon:stock:" + cardRequest.getCardId();
        String userSetKey = "coupon:claimed_users:" + cardRequest.getCardId();

        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(CLAIM_COUPON_LUA_SCRIPT, Long.class);

        Long result = (Long) redisTemplate.execute(
                redisScript,
                Arrays.asList(stockKey, userSetKey),
                String.valueOf(cardRequest.getUserId())
        );

        if (result == null) {
            throw new Exception("Redis脚本执行失败，无法获取返回值");
        }

        // 2. 根据脚本返回值处理业务逻辑
        if (result == 0) { // 抢券成功
            Card claimedCardDetails = cardMapper.getCardDetailsById(cardRequest.getCardId());
            if (claimedCardDetails == null) {
                throw new Exception("严重的数据不一致：Redis中有券，但数据库中没有。CardId: " + cardRequest.getCardId());
            }

            // 3. 发送简单的MQ消息
//            HashMap<String, Long> messagePayload = new HashMap<>();
//            messagePayload.put("userId", (long)cardRequest.getUserId());
//            messagePayload.put("cardId", (long)cardRequest.getCardId());
//            streamBridge.send("couponOrder-out-0", messagePayload);
//            log.info("领券成功，已发送MQ消息。userId: {}, cardId: {}", cardRequest.getUserId(), cardRequest.getCardId());


            cardMapper.addCard(cardRequest);
            return claimedCardDetails;

        } else if (result == 1) {
            throw new Exception("您已领取过该优惠券，请勿重复领取");
        } else if (result == 2) {
            throw new Exception("来晚一步，该优惠券已被领完");
        } else {
            throw new Exception("领取优惠券时发生未知错误");
        }
    }

    @Override
    public void initializeCouponStock(Integer cardId,int stock){
        String stockKey = "coupon:stock:"+cardId;
        redisTemplate.opsForValue().set(stockKey, stock);
    }

    @Override
    public List<HashMap<String, Object>> getCardList(int userId) {
        return cardMapper.getCardList(userId);
    }

    @Override
    public List<Card> allCard() {
        return cardMapper.allCard();
    }

    public List<Card> getCard(Integer userId) {
        List<Card> card = cardMapper.getCard(userId);
        return card;
    }
    @Override
    public CardVO haveCard(int userId, int cardId) {
        return cardMapper.haveCard(userId, cardId);
    }

    @Override
    public List<HashMap<String, Object>> searchCard(String cardName) {
        return cardMapper.searchCard(cardName);
    }

}
